﻿/*
 * Rappelz: Endless Odyssey - The first free open source Rappelz server emulator
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rappelz.GameServer.X2D
{
    public enum CcwResult : int
    {
        Parallelism = 0,
        ClockWise = 1,
        CounterClockWise = -1,
    }

    public class PointBasef
    {
        public float x;
        public float y;
    }


    public class Pointf
    {
        public Pointf()
            : base()
        {
            //            x = 0;
            //            y = 0;
        }

        public Pointf(float _x, float _y)
            : base()
        {
            x = _x;
            y = _y;
        }

        public float GetX()
        {
            return x;
        }
        public float GetY()
        {
            return y;
        }
        // Function       :   public struct X2D::Point<float> operator+(const struct X2D::Point<float> &)
        // Function       :   public struct X2D::Point<float> operator-(const struct X2D::Point<float> &)
        // Function       :   public struct X2D::Point<float> & operator+=(const struct X2D::Point<float> &)
        // Function       :   public struct X2D::Point<float> & operator-=(const struct X2D::Point<float> &)
        // Function       :   public struct X2D::Point<float> operator*(float)
        // Function       :   public struct X2D::Point<float> operator/(float)
        // Function       :   public struct X2D::Point<float> & operator*=(float)
        // Function       :   public struct X2D::Point<float> & operator/=(float)

        public void Set(float _x, float _y)
        {
            x = _x;
            y = _y;
        }

        public float GetAlternativeDistance(Pointf rh)
        {
            float v2;
            float v3;

            v2 = this.x - rh.x;
            v3 = this.y - rh.y;
            if (v2 < 0)
                v2 = -v2;
            if (v3 < 0)
                v3 = -v3;
            return v3 + v2;
        }

        public float GetDistance(Pointf rh)
        {
            return (float)Math.Sqrt((this.x - rh.x) * (this.x - rh.x) + (this.y - rh.y) * (this.y - rh.y));
        }

        public float x;
        public float y;

    }

    public class Linef
    {
        public enum IntersectResult : int
        {
            None = 157,
            Intersect = 1,
            Seperate = -1,
            Touch = 0,
        }

        public Linef()
        {
            begin = new Pointf();
            end = new Pointf();
        }

//         Function       :   public void Line<float>(const float &, const float &, const float &, const float &)
        public Linef(Pointf p1, Pointf p2)
        {
            begin = new Pointf(p1.x,p1.y);
            end = new Pointf(p2.x, p2.y);
        }
//         Function       :   public float GetBeginX()
//         Function       :   public float GetBeginY()
//         Function       :   public float GetEndX()
//         Function       :   public float GetEndY()
//         Function       :   public float GetLength()
//         Function       :   public float GetLeftX()
//         Function       :   public float GetRightX()
//         Function       :   public float GetTopY()
//         Function       :   public float GetBottomY()
//         Function       :   public bool Has(const struct X2D::Point<float> &)
//         Function       :   public bool IsCollision(const struct X2D::Line<float> &)
//         Function       :   public bool GetIntersectPoint(const struct X2D::Line<float> &, struct X2D::Point<float> *)
//         Function       :   public static bool GetIntersectPoint(const struct X2D::Line<float> &, const struct X2D::Line<float> &, struct X2D::Point<float> *)
//         Function       :   public static bool GetIntersectPoint(const struct X2D::Point<float> &, const struct X2D::Point<float> &, const struct X2D::Point<float> &, const struct X2D::Point<float> &, struct X2D::Point<float> *)
//         Function       :   public enum X2D::Line<float>::INTERSECT_RESULT IntersectCCW(const struct X2D::Line<float> &)
//         Function       :   public enum X2D::Line<float>::INTERSECT_RESULT IntersectCCW(const struct X2D::Point<float> &, const struct X2D::Point<float> &)
//         Function       :   public enum X2D::Line<float>::INTERSECT_RESULT IntersectCCW(const struct X2D::Line<float> &, const struct X2D::Line<float> &)

        public static CcwResult CheckClockWisef(float x1, float y1, float x2, float y2, float x3, float y3)
        {
            CcwResult result;
            float l = ((y3 - y1) * (x2 - x1)) - ((x3 - x1) * (y2 - y1));
            if ( l <= 0.0f )
            {
                if ( l >= 0.0f )
                    result = CcwResult.Parallelism;
                else
                    result = CcwResult.CounterClockWise;
            }
            else
            {
                result = CcwResult.ClockWise;
            }
            return result;
        }
                
        public static CcwResult CheckClockWisef(Pointf pt1, Pointf pt2, Pointf pt3)
        {
            return CheckClockWisef(pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y);
        }

        public static IntersectResult IntersectCCW(X2D.Pointf p1, X2D.Pointf p2, X2D.Pointf p3, X2D.Pointf p4)
        {
            if (Math.Max(p3.y,p4.y) < Math.Min(p1.y,p2.y)
              || Math.Max(p1.y,p2.y) < Math.Min(p3.y,p4.y)
              || Math.Max(p3.x,p4.x) < Math.Min(p1.x,p2.x)
              || Math.Max(p1.x,p2.x) < Math.Min(p3.x,p4.x))
                return IntersectResult.Seperate;

            Pointf tp1;
            Pointf tp2;
            Pointf tp3;
            Pointf tp4;
            Pointf tp5;
            Pointf tp6;
            Pointf tp7;
            Pointf tp8;
            float f1;
            float f2;

            if (p2.x >= p1.x)
            {
                tp1 = p1;
                tp2 = p2;
            }
            else
            {
                tp1 = p2;
                tp2 = p1;
            }
            if (p2.x >= p3.x)
            {
                tp3 = p3;
                tp4 = p4;
            }
            else
            {
                tp3 = p4;
                tp4 = p3;
            }
            CcwResult ccw123 = CheckClockWisef(tp1, tp2, tp3);
            CcwResult ccw124 = CheckClockWisef(tp1, tp2, tp4);
            CcwResult ccw341 = CheckClockWisef(tp3, tp4, tp1);
            CcwResult ccw342 = CheckClockWisef(tp3, tp4, tp2);
            
            if ((int)ccw123 * (int)ccw124 < 0 && (int)ccw341 * (int)ccw342 < 0 )
                return IntersectResult.Intersect;
            if ( ccw123 != CcwResult.Parallelism || ccw124 != CcwResult.Parallelism)
            {
                if (ccw123 != CcwResult.Parallelism && ccw124 != CcwResult.Parallelism && ccw341 != CcwResult.Parallelism && ccw342 != CcwResult.Parallelism)
                    return IntersectResult.Seperate;

                tp5 = tp2;
                if (tp2.y >= tp1.y)
                {
                    tp6 = tp1;
                }
                else
                {
                    tp6 = tp2;
                    tp2 = tp1;
                }
                if (ccw123 != CcwResult.Parallelism)
                {
                    if (tp3.x < tp1.x || tp5.x < tp3.x)
                        return IntersectResult.Seperate;
                    if (tp1.x != tp3.x || tp5.x != tp1.x)
                        return IntersectResult.Touch;
                    if (tp3.y >= tp6.y )
                    {
                        f1 = tp2.y;
                        f2 = tp3.y;
                        if (f2 <= f1)
                            return IntersectResult.Touch;
                    }
                    return IntersectResult.Seperate;
                }
                if (ccw124 != CcwResult.Parallelism)
                {
                    if (tp3.y >= tp4.y )
                    {
                        tp7 = tp3;
                        tp8 = tp4;
                    }
                    else
                    {
                        tp7 = tp4;
                        tp8 = tp3;
                    }
                    if (ccw341 != CcwResult.Parallelism)
                    {
                        if (ccw342 != CcwResult.Parallelism || tp5.x < tp3.x || tp4.x < tp5.x)
                            return IntersectResult.Seperate;
                        if (tp3.x != tp5.x || tp4.x != tp3.x)
                            return IntersectResult.Touch;
                        if (tp5.y < tp7.y)
                            return IntersectResult.Seperate;
                        f1 = tp8.y;
                        f2 = tp5.y;
                    }
                    else
                    {
                        if (tp1.x < tp3.x || tp4.x < tp1.x)
                            return IntersectResult.Seperate;
                        if (tp3.x != tp1.x || tp4.x != tp3.x )
                            return IntersectResult.Touch;
                        if (tp1.y < tp7.y)
                            return IntersectResult.Seperate;
                        f1 = tp8.y;
                        f2 = tp1.y;
                    }
                }
                else
                {
                    if (tp4.x < tp1.x || tp5.x < tp4.x)
                        return IntersectResult.Seperate;
                    if (tp1.x != tp4.x || tp5.x != tp1.x)
                        return IntersectResult.Touch;
                    if (tp4.y < tp6.y)
                        return IntersectResult.Seperate;
                    f1 = tp2.y;
                    f2 = tp4.y;
                }
                if (f2 <= f1)
                    return IntersectResult.Touch;
                return IntersectResult.Seperate;
            }

            if (tp2.x < tp4.x || tp3.x < tp1.x )
                return IntersectResult.Seperate;
            return IntersectResult.Touch;
        }


//         Function       :   public bool operator==(const struct X2D::Line<float> &)
//         Function       :   public bool operator!=(const struct X2D::Line<float> &)
        public Pointf begin;
        public Pointf end;
    }



    public class Boxf
    {
        public bool IsInclude(float x, float y)
        {
            return x >= begin.x
                && x <= end.x
                && y >= begin.y
                && y <= end.y;
        }

// UserDefinedType: X2D::Box<float>
// Function       :   public void Box<float>()
// Function       :   public void X2D::Box<float>::Box<float>(const float &, const float &, const float &, const float &)
// Function       :   public void X2D::Box<float>::Box<float>(const struct X2D::Point<float> &, const struct X2D::Point<float> &)
// Function       :   public float GetX()
// Function       :   public float GetY()
// Function       :   public float GetLeft()
// Function       :   public float GetTop()
// Function       :   public float GetRight()
// Function       :   public float GetBottom()
// Function       :   public float GetWidth()
// Function       :   public float GetHeight()

        public void SetLeft(float x)
        {
            begin.x = x;
            if (end.x < x)
            {
                begin.x = end.x;
                end.x = x;
            }
        }

        public void SetTop(float y)
        {
            begin.y = y;
            if (end.y < y)
            {
                begin.y = end.y;
                end.y = y;
            }
        }

        public void SetRight(float x)
        {
            end.x = x;
            if (x < begin.x )
            {
                end.x = begin.x;
                begin.x = x;
            }
        }

        public void SetBottom(float y)
        {
            end.y = y;
            if (y < begin.y)
            {
                end.y = begin.y;
                begin.y = y;
            }
        }

// Function       :   public void X2D::Box<float>::SetRight(const float &)
// Function       :   public void X2D::Box<float>::SetBottom(const float &)
// Function       :   public float GetSize()
// Function       :   public void Move(const float &, const float &)
// Function       :   public bool Has(const struct X2D::Line<float> &)
// Function       :   public bool Has(const struct X2D::Point<float> &)
// Function       :   public struct X2D::Point<float> GetCenter()
// Function       :   public bool IsInclude(const struct X2D::Box<float> &)
// Function       :   public bool IsInclude(const struct X2D::Point<float> &)
// Function       :   public bool X2D::Box<float>::IsInclude(const float &, const float &)
// Function       :   public bool IsLooseInclude(const struct X2D::Box<float> &)
// Function       :   public bool IsLooseInclude(const struct X2D::Point<float> &)
// Function       :   public bool IsLooseInclude(const float &, const float &)
// Function       :   public bool IsCollision(const struct X2D::Box<float> &)
// Function       :   public bool IsCollision(const float &, const float &, const float &, const float &)
// Function       :   public bool IsCollision(const struct X2D::Line<float> &)
// Function       :   public bool IsCollision(const struct X2D::Point<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Box<float> &)
// Function       :   public bool IsLooseCollision(const float &, const float &, const float &, const float &)
// Function       :   public bool IsLooseCollision(const struct X2D::Line<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Point<float> &)
// Function       :   public void X2D::Box<float>::Set(const float &, const float &, const float &, const float &)
        public virtual void Set(Pointf _begin, Pointf _end)
        {
            begin.x = _begin.x;
            begin.y = _begin.y;
            end.x = _end.x;
            end.y = _end.y;
            this.normalize();
        }
// Function       :   public const struct X2D::Line<float> GetSegment(unsigned int)
// Function       :   public const struct X2D::Point<float> GetPoint(unsigned int)
// Function       :   public const struct X2D::Point<float> GetLeftTop()
// Function       :   public const struct X2D::Point<float> GetRightTop()
// Function       :   public const struct X2D::Point<float> GetLeftBottom()
// Function       :   public const struct X2D::Point<float> GetRightBottom()
// Function       :   public bool operator==(const struct X2D::Box<float> &)
// Function       :   public bool operator!=(const struct X2D::Box<float> &)

        protected void normalize()
        {
            float t;

            if (end.x < begin.x )
            {
                t = begin.x;
                begin.x = end.x;
                end.x = t;
            }
            if (end.y < begin.y)
            {
                t = begin.y;
                begin.y = end.y;
                end.y = t;
            }
        }

        public Pointf begin = new Pointf();
        public Pointf end = new Pointf();
// Function       :   public struct X2D::Box<float> & X2D::Box<float>::operator=(const struct X2D::Box<float> &)
// 

    }

    public class Rectf
    {

// UserDefinedType: X2D::Rect<float>
// Function       :   public void Rect<float>()
// Function       :   public void Rect<float>(const float &, const float &, const float &, const float &)
// Function       :   public void Rect<float>(const struct X2D::Point<float> &, const struct X2D::Point<float> &)
// Function       :   public float GetX()
// Function       :   public float GetY()
// Function       :   public float GetWidth()
// Function       :   public float GetHeight()
// Function       :   public float GetSize()
// Function       :   public void Move(const float &, const float &)
// Enum           :   TOUCH_POSITION, Type: int
// Data           :     constant 0xFF, Constant, Type: int, SEPARATE
// Data           :     constant 0x0, Constant, Type: int, LEFT
// Data           :     constant 0x1, Constant, Type: int, TOP
// Data           :     constant 0x2, Constant, Type: int, RIGHT
// Data           :     constant 0x3, Constant, Type: int, BOTTOM
// Data           :     constant 0x4, Constant, Type: int, COLLISION
// Function       :   public enum X2D::Rect<float>::TOUCH_POSITION GetTouchPosition(const struct X2D::Rect<float> &)
        public virtual bool IsInclude(float x, float y)
        {
            float x1 = this.size.x+this.pos.x;
            float y1 = this.size.y+this.pos.y;

            return x >= this.pos.x && x < x1 && y >= this.pos.y && y < y1;
        }

        public virtual bool IsInclude(Pointf p)
        {
            float x1 = this.size.x + this.pos.x;
            float y1 = this.size.y + this.pos.y;

            return p.x >= this.pos.x && p.x < x1 && p.y >= this.pos.y && p.y < y1;
        }

// Function       :   public bool IsInclude(const struct X2D::Box<float> &)
// Function       :   public bool IsInclude(const struct X2D::Rect<float> &)
// Function       :   public bool IsInclude(const struct X2D::Point<float> &)
// Function       :   public bool IsLooseInclude(const struct X2D::Box<float> &)
// Function       :   public bool IsLooseInclude(const struct X2D::Rect<float> &)
// Function       :   public bool IsLooseInclude(const struct X2D::Point<float> &)
// Function       :   public bool IsLooseInclude(const float &, const float &)
// Function       :   public bool IsCollision(const struct X2D::Box<float> &)
// Function       :   public bool IsCollision(const struct X2D::Rect<float> &)
// Function       :   public bool IsCollision(const struct X2D::Line<float> &)
// Function       :   public bool IsCollision(const struct X2D::Point<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Box<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Rect<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Line<float> &)
// Function       :   public bool IsLooseCollision(const struct X2D::Point<float> &)
// Function       :   public void Set(const float &, const float &, const float &, const float &)

        public virtual bool Set(Pointf begin, Pointf end)
        {
            this.pos.x = begin.x;
            this.pos.y = begin.y;
            this.size.x = end.x - begin.x;
            this.size.y = end.y - begin.y;
            return true;
//             X2D::Polygon<float> *v3; // esi@1
//             bool v4; // al@1
// 
//             v3 = this;
//             this.Clear();
//             this.m_vList.
//             std::vector<ArModifyTag_std::allocator<ArModifyTag>>::reserve(&v3->m_vList, end - begin);
//             std::vector<X2D::Point<float>_std::allocator<X2D::Point<float>>>::_Assign<X2D::Point<float>__>(
//                 &v3->m_vList,
//                 begin,
//                 end,
//                 end);
//             X2D::Polygon<float>::RemoveDuplicatedPoint(v3);
//             v4 = X2D::Polygon<float>::isValid(v3, &v3->m_vList);
//             v3->m_bIsValid = v4;
//             if ( v4 )
//             {
//                 v3->m_bIsClockWise = X2D::Polygon<float>::isClockWise(v3);
//                 X2D::Polygon<float>::calculateArea(v3, &v3->m_vList, &v3->m_bxArea);
//             }
//             else
//             {
//                 X2D::Polygon<float>::Clear(v3);
//             }
        }
// Function       :   public void SetWidth(const float &)
// Function       :   public void SetHeight(const float &)
// Function       :   public float GetLeft()
// Function       :   public float GetTop()
// Function       :   public float GetRight()
// Function       :   public float GetBottom()
// Function       :   public const struct X2D::Point<float> GetLeftTop()
// Function       :   public const struct X2D::Point<float> GetRightTop()
// Function       :   public const struct X2D::Point<float> GetLeftBottom()
// Function       :   public const struct X2D::Point<float> GetRightBottom()
// Function       :   public bool operator==(const struct X2D::Rect<float> &)
// Function       :   public bool operator!=(const struct X2D::Rect<float> &)

        public X2D.Pointf pos = new X2D.Pointf();          // 0x0
        public X2D.Pointf size = new X2D.Pointf();         // 0x8
    }

    public class Polygonf : Rectf
    {

        public override bool Set(Pointf _begin, Pointf _end)
        {
            this.Clear();

            this.m_vList.Add(new Pointf(_begin.x, _begin.y));
            this.m_vList.Add(new Pointf(_begin.x, _end.y));
            this.m_vList.Add(new Pointf(_end.x, _end.y));
            this.m_vList.Add(new Pointf(_end.x, _begin.y));
//            this.m_vList.Add(_end);

            this.RemoveDuplicatedPoint();
            this.m_bIsValid = this.isValid(this.m_vList);

            if (this.m_bIsValid)
            {
                this.m_bIsClockWise = this.isClockWise();
                this.calculateArea(this.m_vList, this.m_bxArea);
                this.calculateRect();

            }
            else
            {
                this.Clear();
            }
            return this.m_bIsValid;
        }

        public bool Set()
        {
            this.RemoveDuplicatedPoint();
            this.m_bIsValid = this.isValid(this.m_vList);

            if (this.m_bIsValid)
            {
                this.m_bIsClockWise = this.isClockWise();
                this.calculateArea(this.m_vList, this.m_bxArea);
                this.calculateRect();
            }
            else
            {
                this.Clear();
            }
            return this.m_bIsValid;
        }

        public bool IsIn(X2D.Rectf t)
        {
            foreach (Pointf p in this.m_vList)
            {
                if(!t.IsInclude(p.x, p.y))
                    return false;
            }
            return true;
        }

        public void RemoveDuplicatedPoint()
        {
/*
            X2D::Polygon<float> *v1; // ebx@1
            std::pair<StructSkill *,int> *v2; // eax@2
            float v3; // ecx@2
            float v4; // eax@2
            unsigned int *v5; // ST04_4@2
            ArMoveVector::MOVE_INFO *v6; // eax@4
            ArMoveVector::MOVE_INFO *v7; // eax@6
            ArMoveVector::MOVE_INFO *v8; // edi@7
            ArMoveVector::MOVE_INFO *v9; // eax@7
            ArMoveVector::MOVE_INFO *v10; // eax@7
            int v11; // eax@10
            std::_Vector_iterator<X2D::Point<float>,std::allocator<X2D::Point<float> > > target_it; // [sp+4h] [bp-28h]@2
            std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > _Right; // [sp+Ch] [bp-20h]@2
            std::_Vector_iterator<X2D::Point<float>,std::allocator<X2D::Point<float> > > new_it; // [sp+14h] [bp-18h]@2
            X2D::Point<float> prevPt; // [sp+1Ch] [bp-10h]@2
            std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > thisa; // [sp+24h] [bp-8h]@2

            v1 = this;
            if (this.m_bIsValid )
            {
                v2 = std::vector<std::pair<StructSkill___int>_std::allocator<std::pair<StructSkill___int>>>::back(&this->m_vList);
                LODWORD(v3) = this.first;
                LODWORD(v4) = this.second;
                v5 = v1->m_vList._Myfirst;
                prevPt.baseclass_0.x = v3;
                prevPt.baseclass_0.y = v4;
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &new_it,
                    v5,
                    &v1->m_vList.baseclass_0.___u0.baseclass_0);
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &target_it,
                    v1->m_vList._Myfirst,
                    &v1->m_vList.baseclass_0.___u0.baseclass_0);
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &thisa,
                    v1->m_vList._Myfirst,
                    &v1->m_vList.baseclass_0.___u0.baseclass_0);
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &_Right,
                    v1->m_vList._Mylast,
                    &v1->m_vList.baseclass_0.___u0.baseclass_0);
                while ( !std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                             &thisa,
                             &_Right) )
                {
                    std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                        &target_it,
                        v1->m_vList._Myfirst,
                        &v1->m_vList.baseclass_0.___u0.baseclass_0);
                    if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                             &thisa,
                             &target_it) )
                    {
                        v6 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&new_it);
                        if ( !X2D::PointBase<float>::operator__(&prevPt.baseclass_0, v6) )
                            goto LABEL_8;
                    }
                    else
                    {
                        v7 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&thisa);
                        if ( !X2D::PointBase<float>::operator__(&prevPt.baseclass_0, v7) )
                        {
                            v8 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&thisa);
                            v9 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&new_it);
                            v9->end.x = v8->end.x;
                            v9->end.y = v8->end.y;
                            v10 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&thisa);
                            prevPt.baseclass_0.x = v10->end.x;
                            prevPt.baseclass_0.y = v10->end.y;
        LABEL_8:
                            std::_Vector_const_iterator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>_std::allocator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>>>::operator__(&new_it);
                            goto LABEL_9;
                        }
                    }
        LABEL_9:
                    std::_Vector_const_iterator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>_std::allocator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>>>::operator__(&thisa);
                    std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                        &_Right,
                        v1->m_vList._Mylast,
                        &v1->m_vList.baseclass_0.___u0.baseclass_0);
                }
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &target_it,
                    v1->m_vList._Myfirst,
                    &v1->m_vList.baseclass_0.___u0.baseclass_0);
                v11 = std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator_(
                          &new_it,
                          &target_it);
                std::vector<X2D::Point<float>_std::allocator<X2D::Point<float>>>::resize(&v1->m_vList, v11);
                if ( std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(&v1->m_vList) < 3 )
                    X2D::Polygon<float>::Clear(v1);
            }
*/
        }

        // VTable         :   , Type:  *
        // Typedef        :   , Type: struct X2D::Point<float>
        // Typedef        :   , Type: struct X2D::Line<float>
        // Typedef        :   , Type: struct X2D::Box<float>
        // Typedef        :   , Type: struct X2D::Rect<float>
        // Function       :   public void X2D::Polygon<float>::Polygon<float>(const struct X2D::Polygon<float> &)
        // Function       :   public void Polygon<float>(const struct X2D::Box<float> &)
        // Function       :   public void X2D::Polygon<float>::Polygon<float>()
        // Function       :   public void ~Polygon<float>()
        // Function       :   public bool Scale(float, bool)
        // Function       :   public void X2D::Polygon<float>::Clear()
        // Function       :   public void Reverse()
        // Function       :   public bool IsClockWise()
        // Function       :   public void MakeToClockwise()
        // Function       :   public bool Has(const struct X2D::Line<float> &)
        // Function       :   public bool Has(const struct X2D::Point<float> &)
        // Function       :   public const struct X2D::Box<float> & GetBoundingBox()
        // Function       :   public bool IsInclude(const struct X2D::Polygon<float> &)
        // Function       :   public bool IsInclude(const float &, const float &)
        // Function       :   public bool X2D::Polygon<float>::IsInclude(const struct X2D::Point<float> &)
        // Function       :   public bool IsLooseInclude(const float &, const float &)
        // Function       :   public bool IsLooseInclude(const struct X2D::Point<float> &)
        // Function       :   public bool IsValid()

        public override bool IsInclude(X2D.Pointf pt)
        {
            X2D.Pointf farAway = new X2D.Pointf();
            int nTouchCnt;
            int nIntersectCnt;

            Pointf tp1;
            Pointf tp2;

            bool result = this.m_bxArea.IsInclude(pt.x, pt.y);
            if (result)
            {
                nTouchCnt = 0;
                nIntersectCnt = 0;

                //v5 = this.m_vList;
                farAway.x = this.m_bxArea.end.x + 1.0f;
                farAway.y = pt.y;

                if (this.m_vList.Count > 0)
                {
                    for(int i = 0; i < m_vList.Count; ++i)
                    {
                        tp1 = m_vList[i];
                        if (tp1.x == pt.x && tp1.y == pt.y)
                            return true;

                        int i2 = i != this.m_vList.Count-1 ? i+1 : 0;
                        tp2 = m_vList[i2];
                        Linef.IntersectResult ir = X2D.Linef.IntersectCCW(tp1, tp2, farAway, pt);
                        if (ir == Linef.IntersectResult.Intersect)
                            ++nIntersectCnt;
                        if (ir == Linef.IntersectResult.Touch)
                        {
                            if (Math.Min(tp1.y, tp2.y) == pt.y )
                            {
                                if (tp2.y != tp1.y )
                                    ++nTouchCnt;
                            }
                        }
                    }
                }
                result = ((nTouchCnt + nIntersectCnt) & 1) == 1;
            }
            return result;
        }

        public X2D.Linef GetSegment(uint idx)
        {
            uint idx2 = idx != this.m_vList.Count - 1 ? idx + 1 : 0;
            Pointf p1 = this.m_vList[(int)idx];
            Pointf p2 = this.m_vList[(int)idx2];
            return new Linef(p1,p2);
        }

        public void Clear()
        {
            m_vList.Clear();
            m_bxArea.Set(new Pointf(), new Pointf());
            m_bIsClockWise = false;
            m_bIsValid = false;
        }

        // Function       :   public bool operator==(const struct X2D::Polygon<float> &)


        public bool IsCollision(X2D.Rectf rc)
        {
            Linef line_a = new Linef();
            Linef line_b = new Linef();
            Linef line_c = new Linef();
            Linef line_d = new Linef();
            Linef line = new Linef();

            line.end.x = rc.pos.x;
            line.end.y = rc.pos.y;

            if (this.IsInclude(line.end))
            {
                return true;
            }
            else
            {
                foreach (Pointf p1 in this.m_vList)
                {
                    if(rc.IsInclude(p1))
                        return true;
                }
                float rsx = rc.size.x + rc.pos.x;
                float rsy = rc.size.y + rc.pos.y;

                line_a.begin.x = rc.pos.x;
                line_a.begin.y = rc.pos.y;
                line_a.end.x = rsx;
                line_a.end.y = rc.pos.y;
                line_b.begin.x = rsx;
                line_b.begin.y = rc.pos.y;
                line_b.end.x = rsx;
                line_b.end.y = rsy;
                line_c.begin.y = rsy;
                line_c.begin.x = rsx;
                line_c.end.x = rc.pos.x;
                line_c.end.y = rsy;
                line_d.begin.x = rc.pos.x;
                line_d.begin.y = rsy;
                line_d.end.x = rc.pos.x;
                line_d.end.y = rc.pos.y;

                for(int i = 0; i < this.m_vList.Count;++i)
                {
                    line = this.GetSegment((uint)i);
                    if (X2D.Linef.IntersectCCW(line.begin, line.end, line_a.begin, line_a.end) == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    X2D.Linef.IntersectResult r1 = X2D.Linef.IntersectCCW(line.begin, line.end, line_b.begin, line_b.end);
                    if (r1 == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    X2D.Linef.IntersectResult r2 = X2D.Linef.IntersectCCW(line.begin, line.end, line_c.begin, line_c.end);
                    if (r2 == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    if (X2D.Linef.IntersectCCW(line.begin, line.end, line_d.begin, line_d.end) == X2D.Linef.IntersectResult.Intersect
                      || line.end.x != line.begin.x
                      && line.end.y != line.begin.y
                      && r1 == X2D.Linef.IntersectResult.Touch
                      && r2 == X2D.Linef.IntersectResult.Touch)
                        return true;
                }
            }
            return false;
        }
        // Function       :   public bool IsCollision(const struct X2D::Polygon<float> &)
        // Function       :   public bool IsCollision(const struct X2D::Line<float> &)
        // Function       :   public bool X2D::Polygon<float>::IsCollision(const struct X2D::Rect<float> &)
        // Function       :   public bool IsCollision(const struct X2D::Box<float> &)
        // Function       :   public bool IsCollision(const struct X2D::Point<float> &)
        // Function       :   public bool IsLooseCollision(const struct X2D::Polygon<float> &)
        // Function       :   public bool IsLooseCollision(const struct X2D::Line<float> &)
        // Function       :   public bool IsLooseCollision(const struct X2D::Rect<float> &)
        // Function       :   public bool IsLooseCollision(const struct X2D::Box<float> &)
        // Function       :   public bool IsLooseCollision(const struct X2D::Point<float> &)
        // Function       :   public void X2D::Polygon<float>::RemoveDuplicatedPoint()
        // Function       :   public unsigned int Size()
        // Function       :   public const struct X2D::Point<float> & GetPoint(unsigned int)
        // Function       :   public const struct X2D::Point<float> * GetRawPoint()
        // Function       :   public struct X2D::Point<float> GetCenter()
        // Function       :   public const float GetTop()
        // Function       :   public const float GetBottom()
        // Function       :   public const float GetLeft()
        // Function       :   public const float GetRight()
        // Function       :   public unsigned int getPrevIndex(unsigned int)
        // Function       :   public unsigned int getNextIndex(unsigned int)

        protected bool isValid(List<Pointf> vList)
        {
            return true;
/*
            std::vector<X2D::Point<float>,std::allocator<X2D::Point<float> > > *v2; // ebx@1
            bool v3; // al@2
            std::_Vector_const_iterator<X2D::Point<int>,std::allocator<X2D::Point<int> > > *v4; // eax@4
            std::_Container_base *v5; // ecx@4
            X2D::Point<float> *v6; // eax@4
            ArMoveVector::MOVE_INFO *v7; // ST14_4@5
            ArMoveVector::MOVE_INFO *v8; // eax@5
            std::vector<ArModifyTag,std::allocator<ArModifyTag> > *v9; // edi@12
            unsigned int v10; // eax@12
            unsigned int v11; // esi@12
            unsigned int v12; // eax@12
            ArObject **v13; // edi@12
            X2D::Point<float> *v14; // ST0C_4@12
            X2D::Point<float> *v15; // ST08_4@12
            X2D::Point<float> *v16; // ST04_4@12
            X2D::Point<float> *v17; // eax@12
            X2D::Line<float>::INTERSECT_RESULT v18; // eax@12
            std::_Vector_const_iterator<X2D::Point<int>,std::allocator<X2D::Point<int> > > result; // [sp+4h] [bp-2Ch]@4
            std::_Vector_const_iterator<unsigned int,std::allocator<unsigned int> > thisa; // [sp+Ch] [bp-24h]@3
            X2D::Polygon<float> *v21; // [sp+14h] [bp-1Ch]@1
            std::_Vector_const_iterator<X2D::Point<float>,std::allocator<X2D::Point<float> > > cur_it; // [sp+18h] [bp-18h]@3
            std::_Vector_const_iterator<X2D::Point<float>,std::allocator<X2D::Point<float> > > target_it; // [sp+20h] [bp-10h]@3
            std::_Vector_const_iterator<ArObject *,std::allocator<ArObject *> > _Right; // [sp+28h] [bp-8h]@7
            X2D::Point<float> *idx_2; // [sp+38h] [bp+8h]@11

            v2 = vList;
            v21 = this;
            if ( std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(vList) >= 3 )
            {
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &cur_it,
                    vList->_Myfirst,
                    &vList->baseclass_0.___u0.baseclass_0);
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &target_it,
                    vList->_Myfirst,
                    &vList->baseclass_0.___u0.baseclass_0);
                std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                    &thisa,
                    vList->_Myfirst,
                    &vList->baseclass_0.___u0.baseclass_0);
                cur_it.baseclass_0.baseclass_0._Mycont = thisa.baseclass_0.baseclass_0._Mycont;
                cur_it._Myptr = thisa._Myptr;
                while ( 1 )
                {
                    std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                        &thisa,
                        vList->_Mylast,
                        &vList->baseclass_0.___u0.baseclass_0);
                    if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                             &cur_it,
                             &thisa) )
                        break;
                    v4 = std::_Vector_const_iterator<X2D::Point<int>_std::allocator<X2D::Point<int>>>::operator_(
                             &cur_it,
                             &result,
                             1);
                    v5 = v4->baseclass_0.baseclass_0._Mycont;
                    v6 = v4->_Myptr;
                    target_it.baseclass_0.baseclass_0._Mycont = v5;
                    target_it._Myptr = v6;
                    while ( 1 )
                    {
                        std::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>::_Vector_const_iterator<StateDamage_std::allocator<StateDamage>>(
                            &_Right,
                            vList->_Mylast,
                            &vList->baseclass_0.___u0.baseclass_0);
                        if ( std::_Vector_const_iterator<X2D::Point<float>_std::allocator<X2D::Point<float>>>::operator__(
                                 &target_it,
                                 &_Right) )
                            break;
                        v7 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&cur_it);
                        v8 = std::_Vector_const_iterator<PartyManager::PartyInfo___std::allocator<PartyManager::PartyInfo__>>::operator_(&target_it);
                        if ( X2D::PointBase<float>::operator__(v8, v7) )
                            goto LABEL_2;
                        std::_Vector_const_iterator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>_std::allocator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>>>::operator__(&target_it);
                    }
                    std::_Vector_const_iterator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>_std::allocator<std::pair<GameContent::HUNTAHOLIC_MONSTER_RESPAWN_INFO_const___unsigned_long>>>::operator__(&cur_it);
                }
                _Right._Myptr = 0;
                if ( std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(vList) )
                {
                    while ( 1 )
                    {
                        cur_it._Myptr = (_Right._Myptr + 1);
                        idx_2 = (_Right._Myptr + 1);
                        if ( (_Right._Myptr + 1) < std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v2) )
                            break;
        LABEL_17:
                        _Right._Myptr = cur_it._Myptr;
                        if ( cur_it._Myptr >= std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v2) )
                            goto LABEL_18;
                    }
                    while ( 1 )
                    {
                        v9 = &v21->m_vList;
                        v10 = std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(&v21->m_vList);
                        v11 = (_Right._Myptr != (v10 - 1) ? cur_it._Myptr : 0);
                        target_it._Myptr = (idx_2 + 1);
                        v12 = std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v9);
                        v13 = (idx_2 != (v12 - 1) ? target_it._Myptr : 0);
                        v14 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v2, v13);
                        v15 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(
                                  v2,
                                  idx_2);
                        v16 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v2, v11);
                        v17 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(
                                  v2,
                                  _Right._Myptr);
                        v18 = X2D::Line<float>::IntersectCCW(v17, v16, v15, v14);
                        if ( v18 == 1 )
                            break;
                        if ( !v18 && v11 != idx_2 && _Right._Myptr != v13 )
                            break;
                        idx_2 = target_it._Myptr;
                        if ( target_it._Myptr >= std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v2) )
                            goto LABEL_17;
                    }
                    v3 = 0;
                }
                else
                {
        LABEL_18:
                    v3 = 1;
                }
            }
            else
            {
        LABEL_2:
                v3 = 0;
            }
            return v3;
*/
        }

        protected bool isClockWise()
        {
            return false;
/*
            std::vector<ArModifyTag,std::allocator<ArModifyTag> > *v1; // edi@1
            unsigned int v2; // ebx@1
            unsigned int v3; // esi@1
            double v4; // ST24_8@2
            int v5; // eax@7
            unsigned int v6; // ST30_4@9
            unsigned int v7; // esi@9
            const float *v8; // ST14_4@9
            ArModifyTag *v9; // ST10_4@9
            const float *v10; // ST0C_4@9
            ArModifyTag *v11; // ST08_4@9
            const float *v12; // ST04_4@9
            ArModifyTag *v13; // eax@9
            X2D::CCW_RESULT v14; // esi@9
            int v16; // [sp+10h] [bp-Ch]@9
            unsigned int cnt; // [sp+14h] [bp-8h]@5

            v1 = &this->m_vList;
            v2 = 0;
            v3 = 0;
            if ( std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(&this->m_vList) )
            {
                do
                {
                    v4 = *&std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v2)->pObj;
                    if ( *&std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v3)->pObj < v4 )
                        v2 = v3;
                    ++v3;
                }
                while ( v3 < std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v1) );
            }
            cnt = 0;
            while ( 1 )
            {
                v5 = v2 ? v2 - 1 : std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v1) - 1;
                v6 = v5;
                v16 = v2 + 1;
                v7 = v2 != std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v1) - 1 ? v2 + 1 : 0;
                v8 = &std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v7)->bFlag;
                v9 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v7);
                v10 = &std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v2)->bFlag;
                v11 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v2);
                v12 = &std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v6)->bFlag;
                v13 = std::vector<XPerformanceGuard::_TAG_std::allocator<XPerformanceGuard::_TAG>>::operator__(v1, v6);
                v14 = X2D::CheckClockWise<float>(v13, v12, v11, v10, v9, v8);
                if ( v14 )
                    break;
                ++v2;
                ++cnt;
                if ( cnt > std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v1) )
                    break;
                if ( v16 == std::vector<FieldPropSwitchingData_std::allocator<FieldPropSwitchingData>>::size(v1) )
                    v2 = 0;
            }
            return v14 == 1;
*/
        }

        // Function       :   protected void loop()

        protected void calculateRect()
        {
            this.pos.x = this.m_bxArea.begin.x;
            this.pos.y = this.m_bxArea.begin.y;
            this.size.x = this.m_bxArea.end.x - this.m_bxArea.begin.x;
            this.size.y = this.m_bxArea.end.y - this.m_bxArea.begin.y;
        }


        protected void calculateArea(List<Pointf> vList, Boxf area)
        {
            area.Set(vList.First(), vList.First());

            foreach (Pointf pt in vList)
            {
                if (area.begin.x > pt.x)
                {
                    area.SetLeft(pt.x);
                }
                if ( area.begin.y > pt.y)
                {
                    area.SetTop(pt.y);
                }
                if ( area.end.x < pt.x)
                {
                    area.SetRight(pt.x);
                }
                if ( area.end.y < pt.y)
                {
                    area.SetBottom(pt.y);
                }
            }
        }
        
        public bool m_bIsValid;
        public bool m_bIsClockWise;
        public List<Pointf> m_vList = new List<Pointf>();

        public Boxf m_bxArea = new Boxf();
        // Function       :   public struct X2D::Polygon<float> & X2D::Polygon<float>::operator=(const struct X2D::Polygon<float> &)
        // Function       :   public void __local_vftable_ctor_closure()
        // Function       :   public void * __vecDelDtor(unsigned int)

    }

    public class QuadTreeMli : Boxf
    {
        public class Node : Rectf
        {
            public bool Add(GameContent.MapLocationInfo u)
            {
                bool result = false;
//                 Node fn = null;
// 
//                 result = u.IsCollision(this.m_rcEffectiveArea);
//                 if (result)
//                 {
//                     if (this.m_pNode[0] != null)
//                         fn = this.getFitNode(u);
//                     if (this.m_pNode[0] == null || fn == null || !fn.Add(u))
//                         this.add(u);
//                     result = true;
//                 }
                return result;
            }

            public void Enum(X2D.Pointf c, X2D.QuadTreeMli.FunctorAdaptor f)
            {
                if (this.m_rcEffectiveArea.IsInclude(c.x,c.y))
                {
                    if (this.m_pNode[0] != null)
                    {
                        this.m_pNode[0].Enum(c,f);
                        this.m_pNode[1].Enum(c,f);
                        this.m_pNode[2].Enum(c,f);
                        this.m_pNode[3].Enum(c,f);
                    }

                    foreach (GameContent.MapLocationInfo info in m_vList)
                    {
                        if (info.IsInclude(c))
                        {
                            f.pResult.Add(info);
                        }
                    }
                }
            }

            // Function       :     public void Node(const struct X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10>::Node &)
            // Function       :     private void Node()
            // Function       :     public void Node(unsigned short, const float &, const float &, const float &, const float &)
            // Function       :     public float GetX()
            // Function       :     public float GetY()
            // Function       :     public float GetWidth()
            // Function       :     public float GetHeight()
            // Function       :     public bool hasChildNode()

            // Function       :     public bool IsAddable(const struct GameContent::MapLocationInfo &)
            // Function       :     public bool Has(const struct GameContent::MapLocationInfo &)
            // Function       :     public void Remove(const struct GameContent::MapLocationInfo &)
            // Function       :     public const struct X2D::Rect<float> & GetEffectiveArea()
            // Function       :     public void SetDepth(unsigned short)
            // Function       :     public unsigned int getItemCount()
            private Node getFitNode(GameContent.MapLocationInfo u)
            {
//                 if (u.IsIn(this.m_pNode[0]))
//                     return this.m_pNode[0];
//                 if (u.IsIn(this.m_pNode[1]))
//                     return this.m_pNode[1];
//                 if (u.IsIn(this.m_pNode[2]))
//                     return this.m_pNode[2];
//                 if (u.IsIn(this.m_pNode[3]))
//                     return this.m_pNode[3];
                return null;
            }

            private void add(GameContent.MapLocationInfo u)
            {
                this.m_vList.Add(u);
                if(this.m_vList.Count >= 10)
                {
                    if(this.m_unDepth < 10)
                        this.divide();
                }
            }
 
            // Function       :     private void operator()(const struct GameContent::MapLocationInfo &)
            // Function       :     private void join()

            private void divide()
            {
                if (this.m_pNode[0] == null)
                {
                    this.m_pNode[0] = new Node();
                    this.m_pNode[1] = new Node();
                    this.m_pNode[2] = new Node();
                    this.m_pNode[3] = new Node();

////////////
//                     v7 = this.m_rcEffectiveArea.size.x;
//                     this.m_pNode[3] = v6;
//                     *(v1 - 20) = this.m_rcEffectiveArea.size.x;
//                     v8 = v2->m_unDepth + 1;
//                     v9 = this.m_pNode[0];
//                     *(v1 - 20) = this.m_rcEffectiveArea.size.x * 0.25;
//                     *(v1 - 16) = this.m_rcEffectiveArea.size.y;
//                     *(v1 - 16) = 0.25 * this.m_rcEffectiveArea.size.y;
//                     *(v1 - 24) = this.m_rcEffectiveArea.size.x;
//                     *(v1 - 32) = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.25);
//                     *(v1 - 24) = this.m_rcEffectiveArea.size.y;
//                     *(v1 - 40) = this.m_rcEffectiveArea.size.y - (0.25 * this.m_rcEffectiveArea.size.y);
//                     *(v1 - 28) = this.m_rcEffectiveArea.pos.y;
//                     *(v1 - 24) = this.m_rcEffectiveArea.pos.x;
//                     this.m_pNode[0].m_rcEffectiveArea.pos.x = this.m_rcEffectiveArea.pos.x;
//                     this.m_pNode[0].m_rcEffectiveArea.pos.y = this.m_rcEffectiveArea.pos.y;
// 
//                     this.m_pNode[0].m_rcEffectiveArea.size.x = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.25f);
//                     this.m_pNode[0].m_rcEffectiveArea.size.y = this.m_rcEffectiveArea.size.y - (this.m_rcEffectiveArea.size.y * 0.25f);
// 
//                     *(v1 - 32) = this.m_rcEffectiveArea.pos.y;
//                     v12 = v9 + 1;
//                     v13 = this.m_pNode[1].;
//                     *(v1 - 40) = this.m_rcEffectiveArea.pos.x;
//                     *(v1 - 40) = this.m_rcEffectiveArea.pos.x + (this.m_rcEffectiveArea.size.x * 0.25f);
//                     this.m_pNode[1].m_rcEffectiveArea.pos.x = this.m_rcEffectiveArea.pos.x + (this.m_rcEffectiveArea.size.x * 0.25f);
//                     this.m_pNode[1].m_rcEffectiveArea.pos.y = this.m_rcEffectiveArea.pos.y;
//                     this.m_pNode[1].m_rcEffectiveArea.size.x = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.25f);
//                     this.m_pNode[1].m_rcEffectiveArea.size.y = this.m_rcEffectiveArea.size.y - (this.m_rcEffectiveArea.size.y * 0.25f);
//                     this.m_pNode[1].m_unDepth = v12;
//                     LOWORD(v13) = v2->m_unDepth;
//                     *(v1 - 40) = v2->m_rcEffectiveArea.pos.baseclass_0.y;
//                     v14 = v13 + 1;
//                     v15 = v2->m_pNode[2];
//                     *(v1 - 32) = *(v1 - 40) + *(v1 - 16);
//                     *(v1 - 40) = v2->m_rcEffectiveArea.pos.baseclass_0.x;
//                     v15->m_rcEffectiveArea.pos.baseclass_0.x = *(v1 - 40);
//                     v15->m_rcEffectiveArea.pos.baseclass_0.y = *(v1 - 32);
//                     v15->m_rcEffectiveArea.size.x = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.25f);
//                     v15->m_rcEffectiveArea.size.y = this.m_rcEffectiveArea.size.y - (this.m_rcEffectiveArea.size.y * 0.25f);
//                     v15->m_unDepth = v14;
//                     *(v1 - 40) = v2->m_rcEffectiveArea.pos.baseclass_0.y;
//                     v16 = v2->m_unDepth + 1;
//                     v17 = v2->m_pNode[3];
//                     *(v1 - 32) = *(v1 - 40) + *(v1 - 16);
//                     *(v1 - 40) = v2->m_rcEffectiveArea.pos.baseclass_0.x;
//                     *(v1 - 40) = *(v1 - 40) + *(v1 - 20);
//                     v17->m_rcEffectiveArea.pos.baseclass_0.x = *(v1 - 40);
//                     v17->m_rcEffectiveArea.pos.baseclass_0.y = *(v1 - 32);
//                     v17->m_rcEffectiveArea.size.x = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.25f);
//                     v17->m_rcEffectiveArea.size.y = this.m_rcEffectiveArea.size.y - (this.m_rcEffectiveArea.size.y * 0.25f);
//                     v17->m_unDepth = v16;
////////////////

                    float easx = this.m_rcEffectiveArea.size.x - (this.m_rcEffectiveArea.size.x * 0.5f);
                    float easy = this.m_rcEffectiveArea.size.y - (this.m_rcEffectiveArea.size.y * 0.5f);
                    float halfx = this.m_rcEffectiveArea.pos.x + (this.m_rcEffectiveArea.size.x * 0.5f);
                    float halfy = this.m_rcEffectiveArea.pos.y + (this.m_rcEffectiveArea.size.y * 0.5f);
                    ushort new_depth = (ushort)(this.m_unDepth + 1);

                    this.m_pNode[0].m_rcEffectiveArea.pos.x = this.m_rcEffectiveArea.pos.x;
                    this.m_pNode[0].m_rcEffectiveArea.pos.y = this.m_rcEffectiveArea.pos.y;
                    this.m_pNode[0].m_rcEffectiveArea.size.x = easx;
                    this.m_pNode[0].m_rcEffectiveArea.size.y = easy;

                    this.m_pNode[0].m_unDepth = new_depth;

                    this.m_pNode[1].m_rcEffectiveArea.pos.x = halfx;
                    this.m_pNode[1].m_rcEffectiveArea.pos.y = this.m_rcEffectiveArea.pos.y;
                    this.m_pNode[1].m_rcEffectiveArea.size.x = easx;
                    this.m_pNode[1].m_rcEffectiveArea.size.y = easy;
                    this.m_pNode[1].m_unDepth = new_depth;

                    this.m_pNode[2].m_rcEffectiveArea.pos.x = this.m_rcEffectiveArea.pos.x;
                    this.m_pNode[2].m_rcEffectiveArea.pos.y = halfy;
                    this.m_pNode[2].m_rcEffectiveArea.size.x = easx;
                    this.m_pNode[2].m_rcEffectiveArea.size.y = easy;
                    this.m_pNode[2].m_unDepth = new_depth;

                    this.m_pNode[3].m_rcEffectiveArea.pos.x = halfx;
                    this.m_pNode[3].m_rcEffectiveArea.pos.y = halfy;
                    this.m_pNode[3].m_rcEffectiveArea.size.x = easx;
                    this.m_pNode[3].m_rcEffectiveArea.size.y = easy;
                    this.m_pNode[3].m_unDepth = new_depth;

                    this.m_pNode[0].pos.x = this.m_pNode[0].m_rcEffectiveArea.pos.x;
                    this.m_pNode[0].pos.y = this.m_pNode[0].m_rcEffectiveArea.pos.y;
                    this.m_pNode[0].size.x = this.m_pNode[0].m_rcEffectiveArea.size.x;
                    this.m_pNode[0].size.y = this.m_pNode[0].m_rcEffectiveArea.size.y;
                    this.m_pNode[1].pos.x = this.m_pNode[1].m_rcEffectiveArea.pos.x;
                    this.m_pNode[1].pos.y = this.m_pNode[1].m_rcEffectiveArea.pos.y;
                    this.m_pNode[1].size.x = this.m_pNode[1].m_rcEffectiveArea.size.x;
                    this.m_pNode[1].size.y = this.m_pNode[1].m_rcEffectiveArea.size.y;
                    this.m_pNode[2].pos.x = this.m_pNode[2].m_rcEffectiveArea.pos.x;
                    this.m_pNode[2].pos.y = this.m_pNode[2].m_rcEffectiveArea.pos.y;
                    this.m_pNode[2].size.x = this.m_pNode[2].m_rcEffectiveArea.size.x;
                    this.m_pNode[2].size.y = this.m_pNode[2].m_rcEffectiveArea.size.y;
                    this.m_pNode[3].pos.x = this.m_pNode[3].m_rcEffectiveArea.pos.x;
                    this.m_pNode[3].pos.y = this.m_pNode[3].m_rcEffectiveArea.pos.y;
                    this.m_pNode[3].size.x = this.m_pNode[3].m_rcEffectiveArea.size.x;
                    this.m_pNode[3].size.y = this.m_pNode[3].m_rcEffectiveArea.size.y;


                    List<GameContent.MapLocationInfo> nl = new List<GameContent.MapLocationInfo>();

                    foreach (GameContent.MapLocationInfo info in this.m_vList)
                    {
                        Node fn = this.getFitNode(info);
                        if(fn != null)
                        {
                            fn.Add(info);
                        }
                        else
                        {
                            nl.Add(info);
                        }
                    }

                    this.m_vList.Clear();
                    this.m_vList = nl;
                }
            }

            // Function       :     private void init(unsigned short, const float &, const float &, const float &, const float &)
            public List<GameContent.MapLocationInfo> m_vList = new List<GameContent.MapLocationInfo>();         // 0x0
            public Rectf m_rcEffectiveArea = new Rectf();                                                       // 0x10
            public Node[] m_pNode = new Node[4];                                                                // 0x20
            public ushort m_unDepth;                                                                            // 0x30
        }

        public class FunctorAdaptor
        {
            public List<GameContent.MapLocationInfo> pResult = new List<GameContent.MapLocationInfo>();
        }
        // UserDefinedType:   _FUNCTOR_ADAPTOR
        // Data           :     this+0x0, Member, Type: class std::vector<GameContent::MapLocationInfo,std::allocator<GameContent::MapLocationInfo> > *, pResult
        // Function       :     public void operator()(const struct GameContent::MapLocationInfo &)

        // Typedef        :   , Type: struct X2D::Box<float>
        // Function       :   public void QuadTree<float,GameContent::MapLocationInfo,1,10,10>(const struct X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10> &)
        // Function       :   public void QuadTree<float,GameContent::MapLocationInfo,1,10,10>(const float &, const float &)
        // Function       :   public void QuadTree<float,GameContent::MapLocationInfo,1,10,10>(const float &, const float &, const float &, const float &)
        // Function       :   public void ~QuadTree<float,GameContent::MapLocationInfo,1,10,10>()
        // Function       :   public void ReInit(const float &, const float &)
        // Function       :   public void ReInit(const float &, const float &, const float &, const float &)
        // Function       :   public float GetX()
        // Function       :   public float GetY()
        // Function       :   public float GetWidth()
        // Function       :   public float GetHeight()
        // Function       :   public bool Add(const struct GameContent::MapLocationInfo &)
        // Function       :   public void Enum(class std::vector<GameContent::MapLocationInfo,std::allocator<GameContent::MapLocationInfo> > *)
        // Function       :   public void Remove(const struct GameContent::MapLocationInfo &)
        // Function       :   public bool Has(const struct GameContent::MapLocationInfo &)
        // Function       :   public unsigned int getItemCount()
        public Node m_masterNode;// = n// Data           :   this+0x0, Member, Type: struct X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10>::Node, 
        // UserDefinedType:     X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10>::Node
        // 
        // Function       :   public struct X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10> & operator=(const struct X2D::QuadTree<float,GameContent::MapLocationInfo,1,10,10> &)
        // Function       :   public void * __vecDelDtor(unsigned int)

    }

    public class RectangleF
    {
        public RectangleF(Pointf p1, Pointf p2)
        {
            m_TopLeft = new Pointf(p1.x, p1.y);
            m_BottomRight = new Pointf(p2.x, p2.y);
            if (p2.x < p1.x)
            {
                m_TopLeft.x = p2.x;
                m_BottomRight.x = p1.x;
            }
            if (p2.y < p1.y)
            {
                m_TopLeft.y = p2.y;
                m_BottomRight.y = p1.y;
            }
        }

        public RectangleF(List<Pointf> points)
        {
            Pointf p1 = points.First();
            m_TopLeft = new Pointf(p1.x, p1.y);
            Pointf p2 = points.Last();
            m_BottomRight = new Pointf(p2.x, p2.y);
            foreach (Pointf p in points)
            {
                if(p.x < m_TopLeft.x)
                    m_TopLeft.x = p.x;
                if(p.y < m_TopLeft.y)
                    m_TopLeft.y = p.y;
                if(p.x > m_BottomRight.x)
                    m_BottomRight.x = p.x;
                if (p.y > m_BottomRight.y)
                    m_BottomRight.y = p.y;

            }
        }

        public virtual bool IsInclude(float x, float y)
        {
            return x >= this.m_TopLeft.x && x < this.m_BottomRight.x && y >= this.m_TopLeft.y && y < this.m_BottomRight.y;
        }

        public virtual bool IsInclude(Pointf p)
        {
            return p.x >= this.m_TopLeft.x && p.x < this.m_BottomRight.x && p.y >= this.m_TopLeft.y && p.y < this.m_BottomRight.y;
        }

        public bool IsCollision(Linef line)
        {
            if (this.m_BottomRight.x - this.m_TopLeft.x == 0 || this.m_BottomRight.y - this.m_TopLeft.y == 0)
                return false;
            if (this.IsInclude((line.end.x + line.begin.x) / 2, (line.end.y + line.begin.y) / 2)
              || this.IsInclude(line.begin.x, line.begin.y)
              || this.IsInclude(line.end.x, line.end.y))
                return true;

            Pointf topBegin = this.m_TopLeft;
            Pointf topEnd = new Pointf(this.m_BottomRight.x, this.m_TopLeft.y); 
            Pointf bottomBegin = new Pointf(this.m_TopLeft.x, this.m_BottomRight.y); 
            Pointf bottomEnd = new Pointf(this.m_BottomRight.x, this.m_BottomRight.y); 
            Pointf leftBegin = new Pointf(this.m_TopLeft.x, this.m_TopLeft.y); 
            Pointf leftEnd = new Pointf(this.m_TopLeft.x, this.m_BottomRight.y); 
            Pointf rightBegin = new Pointf(this.m_BottomRight.x, this.m_TopLeft.y); 
            Pointf rightEnd = new Pointf(this.m_BottomRight.x, this.m_BottomRight.y); 

            Linef.IntersectResult topResult = Linef.IntersectCCW(line.begin, line.end, topBegin, topEnd);
            Linef.IntersectResult bottomResult = Linef.IntersectCCW(line.begin, line.end, bottomBegin, bottomEnd);
            Linef.IntersectResult leftResult = Linef.IntersectCCW(line.begin, line.end, leftBegin, leftEnd);
            Linef.IntersectResult rightResult = Linef.IntersectCCW(line.begin, line.end, rightBegin, rightEnd);

//             None = 157,
//             Intersect = 1,
//             Seperate = -1,
//             Touch = 0,

            if (topResult == Linef.IntersectResult.Intersect
              || bottomResult == Linef.IntersectResult.Intersect
              || leftResult == Linef.IntersectResult.Intersect
              || rightResult == Linef.IntersectResult.Intersect)
            {
                return true;
            }
            if (leftResult != Linef.IntersectResult.Touch)
            {
                if (topResult == Linef.IntersectResult.Touch)
                {
                    return rightResult != Linef.IntersectResult.Touch;
                }
                return false;
            }
            return bottomResult != Linef.IntersectResult.Touch;
        }


        public Pointf m_TopLeft;
        public Pointf m_BottomRight;
    }

    public class PolygonF
    {
        public PolygonF(Pointf p1, Pointf p2)
        {
            this.m_Area = new RectangleF(p1, p2);
            this.m_Points.Add(new Pointf(this.m_Area.m_TopLeft.x,this.m_Area.m_TopLeft.y));
            this.m_Points.Add(new Pointf(this.m_Area.m_BottomRight.x, this.m_Area.m_TopLeft.y));
            this.m_Points.Add(new Pointf(this.m_Area.m_BottomRight.x, this.m_Area.m_BottomRight.y));
            this.m_Points.Add(new Pointf(this.m_Area.m_TopLeft.x, this.m_Area.m_BottomRight.y));
        }

        public PolygonF(List<Pointf> points)
        {
            this.m_Area = new RectangleF(points);
            foreach (Pointf p in points)
            {
                this.m_Points.Add(new Pointf(p.x, p.y));
            }
        }

        public bool IsCollision(RectangleF rc)
        {
            Linef line_a = new Linef();
            Linef line_b = new Linef();
            Linef line_c = new Linef();
            Linef line_d = new Linef();
            Linef line = new Linef();

            line.end.x = rc.m_TopLeft.x;
            line.end.y = rc.m_TopLeft.y;

            if (this.IsInclude(line.end))
            {
                return true;
            }
            else
            {
                foreach (Pointf p1 in this.m_Points)
                {
                    if (rc.IsInclude(p1))
                        return true;
                }
                float rsx = rc.m_BottomRight.x;
                float rsy = rc.m_BottomRight.y;

                line_a.begin.x = rc.m_TopLeft.x;
                line_a.begin.y = rc.m_TopLeft.y;
                line_a.end.x = rsx;
                line_a.end.y = rc.m_TopLeft.y;
                line_b.begin.x = rsx;
                line_b.begin.y = rc.m_TopLeft.y;
                line_b.end.x = rsx;
                line_b.end.y = rsy;
                line_c.begin.y = rsy;
                line_c.begin.x = rsx;
                line_c.end.x = rc.m_TopLeft.x;
                line_c.end.y = rsy;
                line_d.begin.x = rc.m_TopLeft.x;
                line_d.begin.y = rsy;
                line_d.end.x = rc.m_TopLeft.x;
                line_d.end.y = rc.m_TopLeft.y;

                for (int i = 0; i < this.m_Points.Count; ++i)
                {
                    line = this.GetSegment((uint)i);
                    if (X2D.Linef.IntersectCCW(line.begin, line.end, line_a.begin, line_a.end) == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    X2D.Linef.IntersectResult r1 = X2D.Linef.IntersectCCW(line.begin, line.end, line_b.begin, line_b.end);
                    if (r1 == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    X2D.Linef.IntersectResult r2 = X2D.Linef.IntersectCCW(line.begin, line.end, line_c.begin, line_c.end);
                    if (r2 == X2D.Linef.IntersectResult.Intersect)
                        return true;
                    if (X2D.Linef.IntersectCCW(line.begin, line.end, line_d.begin, line_d.end) == X2D.Linef.IntersectResult.Intersect
                      || line.end.x != line.begin.x
                      && line.end.y != line.begin.y
                      && r1 == X2D.Linef.IntersectResult.Touch
                      && r2 == X2D.Linef.IntersectResult.Touch)
                        return true;
                }
            }
            return false;
        }

        public bool IsLooseCollision(Linef line)
        {
            if (!this.IsLooseInclude(line.begin) && !this.IsLooseInclude(line.end))
            {
                for (int i = 0; i < this.m_Points.Count; ++i)
                {
                    Linef l = this.GetSegment((uint)i);
                    Linef.IntersectResult res = Linef.IntersectCCW(l.begin, l.end, line.begin, line.end);
                    if (res != Linef.IntersectResult.Seperate && res != Linef.IntersectResult.Touch)
                        return true;
                }
            }
            return false;
        }

        public bool IsLooseInclude(Pointf pt)
        {
            uint nIntersectCnt = 0;
            Pointf farAway;
            uint nTouchCnt = 0;

            bool result = this.m_Area.IsInclude(pt.x, pt.y);
            if (!result)
                return false;
            if (result)
            {
                farAway = new Pointf(this.m_Area.m_BottomRight.x+1,pt.y);

                Pointf np;

                if (this.m_Points.Count > 0)
                {
                    for (int i = 0; i < this.m_Points.Count; ++i)
                    {
                        Pointf p = this.m_Points[i];

                        if(p.x == pt.x && p.y == pt.y)
                            return false;

                        np = this.m_Points[i >= this.m_Points.Count-1 ? 0 : i+1];

                        Linef.IntersectResult res = Linef.IntersectCCW(p, np, farAway, pt);
                        if (res == Linef.IntersectResult.Intersect)
                            nIntersectCnt++;
                        if (res == Linef.IntersectResult.Touch)
                        {
                            float y = np.y;
                            if (np.y >= p.y)
                                y = p.y;
                            if (pt.y == y)
                            {
                                if (p.y != np.y)
                                    nTouchCnt++;
                            }
                        }
                    }
                }
            }
            result = ((nIntersectCnt + nTouchCnt) & 1) == 1;
            return result;
        }

        public bool IsInclude(X2D.Pointf pt)
        {
            X2D.Pointf farAway = new X2D.Pointf();
            int nTouchCnt;
            int nIntersectCnt;

            Pointf tp1;
            Pointf tp2;

            bool result = this.m_Area.IsInclude(pt.x, pt.y);
//            return result;
            if (result)
            {
                nTouchCnt = 0;
                nIntersectCnt = 0;

                //v5 = this.m_vList;
                farAway.x = this.m_Area.m_BottomRight.x + 1.0f;
                farAway.y = pt.y;

                if (this.m_Points.Count > 0)
                {
                    for (int i = 0; i < m_Points.Count; ++i)
                    {
                        tp1 = m_Points[i];
                        if (tp1.x == pt.x && tp1.y == pt.y)
                            return true;

                        int i2 = i != this.m_Points.Count - 1 ? i + 1 : 0;
                        tp2 = m_Points[i2];
                        Linef.IntersectResult ir = X2D.Linef.IntersectCCW(tp1, tp2, farAway, pt);
                        if (ir == Linef.IntersectResult.Intersect)
                            ++nIntersectCnt;
                        if (ir == Linef.IntersectResult.Touch)
                        {
                            if (Math.Min(tp1.y, tp2.y) == pt.y)
                            {
                                if (tp2.y != tp1.y)
                                    ++nTouchCnt;
                            }
                        }
                    }
                }
                result = ((nTouchCnt + nIntersectCnt) & 1) == 1;
            }
            return result;
        }

        public bool IsIn(X2D.RectangleF t)
        {
            foreach (Pointf p in this.m_Points)
            {
                if (!t.IsInclude(p.x, p.y))
                    return false;
            }
            return true;
        }


        public Linef GetSegment(uint idx)
        {
            uint idx2 = idx != this.m_Points.Count - 1 ? idx + 1 : 0;
            Pointf p1 = this.m_Points[(int)idx];
            Pointf p2 = this.m_Points[(int)idx2];
            return new Linef(p1, p2);
        }



        public List<Pointf> m_Points = new List<Pointf>();
        public RectangleF m_Area;
    }


    public class QuadTreeMapInfo
    {
        public class FunctorAdaptor
        {
            public List<GameContent.MapLocationInfo> pResult = new List<GameContent.MapLocationInfo>();
        }

        public class Node
        {
            public Node(Pointf p1, Pointf p2, ushort depth)
            {
                this.m_Area = new RectangleF(p1, p2);
                m_unDepth = depth;
            }

            public bool Add(PolygonF u)
            {
                bool result;
                Node nn = null;

                result = u.IsCollision(this.m_Area);
                if (result)
                {
                    if (this.m_pNode[0] != null)
                        nn = this.getFitNode(u);
                    if (this.m_pNode[0] == null || nn == null || !nn.Add(u))
                        this.add(u);
                    result = true;
                }
                return result;
            }

            public void Enum(X2D.Pointf c, QuadTreeMapInfo.FunctorAdaptor f)
            {
                if (this.m_Area.IsInclude(c.x, c.y))
                {
                    if (this.m_pNode[0] != null)
                    {
                        this.m_pNode[0].Enum(c, f);
                        this.m_pNode[1].Enum(c, f);
                        this.m_pNode[2].Enum(c, f);
                        this.m_pNode[3].Enum(c, f);
                    }

                    foreach (GameContent.MapLocationInfo info in m_vList)
                    {
                        if (info.IsInclude(c))
                        {
                            f.pResult.Add(info);
                        }
                    }
                }
            }

            public bool Collision(X2D.Pointf c)
            {
                if (this.m_Area.IsInclude(c))
                {
                    foreach (PolygonF p in this.m_vList)
                    {
                        if(p.IsInclude(c))
                            return true;
                    }

                    if (this.m_pNode[0] != null
                      && (this.m_pNode[0].Collision(c)
                       || this.m_pNode[1].Collision(c)
                       || this.m_pNode[2].Collision(c)
                       || this.m_pNode[3].Collision(c)))
                        return true;
                }
                return false;
            }

            public bool LooseCollision(Linef pLine)
            {
                if (this.m_Area.IsCollision(pLine))
                {
                    foreach (PolygonF p in this.m_vList)
                    {
                        if(p.IsLooseCollision(pLine))
                            return true;
                    }

                    if (this.m_pNode[0] != null
                      && (this.m_pNode[0].LooseCollision(pLine)
                       || this.m_pNode[1].LooseCollision(pLine)
                       || this.m_pNode[2].LooseCollision(pLine)
                       || this.m_pNode[3].LooseCollision(pLine)))
                        return true;
                }
                return false;
            }


            private Node getFitNode(PolygonF u)
            {
                if (u.IsIn(this.m_pNode[0].m_Area))
                    return this.m_pNode[0];
                if (u.IsIn(this.m_pNode[1].m_Area))
                    return this.m_pNode[1];
                if (u.IsIn(this.m_pNode[2].m_Area))
                    return this.m_pNode[2];
                if (u.IsIn(this.m_pNode[3].m_Area))
                    return this.m_pNode[3];
                return null;
            }

            private void add(PolygonF u)
            {
                this.m_vList.Add(u);
                if (this.m_vList.Count >= 10)
                {
                    if (this.m_unDepth < 10)
                        this.divide();
                }
            }

            // Function       :     private void operator()(const struct GameContent::MapLocationInfo &)
            // Function       :     private void join()

            private void divide()
            {
                if (this.m_pNode[0] == null)
                {
                    Pointf p1;
                    Pointf p2;

                    float easx = ((this.m_Area.m_BottomRight.x - this.m_Area.m_TopLeft.x) * 0.5f) + this.m_Area.m_TopLeft.x;
                    float easy = ((this.m_Area.m_BottomRight.y - this.m_Area.m_TopLeft.y) * 0.5f) + this.m_Area.m_TopLeft.y;
                    ushort new_depth = (ushort)(this.m_unDepth + 1);

                    p1 = new Pointf(this.m_Area.m_TopLeft.x, this.m_Area.m_TopLeft.y);
                    p2 = new Pointf(this.m_Area.m_TopLeft.x + easx, this.m_Area.m_TopLeft.y + easy);
                    this.m_pNode[0] = new Node(p1,p2,new_depth);

                    p1 = new Pointf(this.m_Area.m_TopLeft.x + easx, this.m_Area.m_TopLeft.y);
                    p1 = new Pointf(this.m_Area.m_BottomRight.x, this.m_Area.m_TopLeft.y + easy);
                    this.m_pNode[1] = new Node(p1, p2, new_depth);

                    p1 = new Pointf(this.m_Area.m_TopLeft.x, this.m_Area.m_TopLeft.y + easx);
                    p2 = new Pointf(this.m_Area.m_TopLeft.x + easx, this.m_Area.m_BottomRight.y);
                    this.m_pNode[2] = new Node(p1, p2, new_depth);

                    p1 = new Pointf(this.m_Area.m_TopLeft.x + easx, this.m_Area.m_TopLeft.y + easx);
                    p2 = new Pointf(this.m_Area.m_BottomRight.x, this.m_Area.m_BottomRight.y);
                    this.m_pNode[3] = new Node(p1, p2, new_depth);

                    List<PolygonF> nl = new List<PolygonF>();

                    foreach (PolygonF info in this.m_vList)
                    {
                        Node fn = this.getFitNode(info);
                        if (fn != null)
                        {
                            fn.Add(info);
                        }
                        else
                        {
                            nl.Add(info);
                        }
                    }

                    this.m_vList.Clear();
                    this.m_vList = nl;
                }
            }


            public List<PolygonF> m_vList = new List<PolygonF>();
            public RectangleF m_Area;
            public Node[] m_pNode = new Node[4];
            public ushort m_unDepth;
        }

        public QuadTreeMapInfo(float width, float height)
        {
            Pointf p1 = new Pointf(0, 0);
            Pointf p2 = new Pointf(width, height);
            m_Area = new RectangleF(p1, p2);
            m_MasterNode = new Node(p1, p2, 0);
        }

        public void Enum(Pointf c, QuadTreeMapInfo.FunctorAdaptor f)
        {
            this.m_MasterNode.Enum(c, f);
        }

        public bool Add(PolygonF u)
        {
            return m_MasterNode.Add(u);
        }

        public bool Collision(X2D.Pointf c)
        {
            return m_MasterNode.Collision(c);
        }


        public Node m_MasterNode;
        public RectangleF m_Area;
    }


}
